package com.hulk.util;

/**
 * 
 */

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;

public class ClassLoaderUtil {
	/**
	 * 加载Java类。 使用全限定类名
	 * 
	 * @paramclassName
	 * @return
	 */
	public static Class loadClass(String className) {
		try {
			return getClassLoader().loadClass(className);
		} catch (ClassNotFoundException e) {
			throw new RuntimeException("class not found '" + className + "'", e);
		}
	}
	
	/**
	 * 加载Java类。 使用全限定类名
	 * 
	 * @paramclassName
	 * @return
	 */
	public static Object loadClassForObject(String className) {
		try {
			return getClassLoader().loadClass(className).newInstance();
		} catch (Exception e) {
			throw new RuntimeException("class not found '" + className + "'", e);
		} 
	}
	
	

	/**
	 * 得到类加载器
	 * 
	 * @return
	 */
	public static ClassLoader getClassLoader() {

		return ClassLoaderUtil.class.getClassLoader();
	}

	/**
	 * 
	 * @param relativePath
	 *            必须传递资源的相对路径。是相对于classpath的路径。如果需要查找classpath外部的资源，需要使用../来查找
	 * @return资源的绝对URL
	 * @throwsMalformedURLException
	 */
	public static URL getExtendResource(String relativePath) throws MalformedURLException {

		if (!relativePath.contains("../")) {
			return getResource(relativePath);

		}
		String classPathAbsolutePath = ClassLoaderUtil.getAbsolutePathOfClassLoaderClassPath();
		if (relativePath.substring(0, 1).equals("/")) {
			relativePath = relativePath.substring(1);
		}

		String wildcardString = relativePath.substring(0, relativePath.lastIndexOf("../") + 3);
		relativePath = relativePath.substring(relativePath.lastIndexOf("../") + 3);
		int containSum = containSum(wildcardString, "../");
		classPathAbsolutePath = cutLastString(classPathAbsolutePath, "/", containSum);
		String resourceAbsolutePath = classPathAbsolutePath + relativePath;
		System.out.println("绝对路径：" + resourceAbsolutePath);
		URL resourceAbsoluteURL = new URL(resourceAbsolutePath);
		return resourceAbsoluteURL;
	}

	/**
	 * 得到URL的输出流
	 * 
	 * @paramurl
	 * @return
	 * @throwsIOException
	 */
	public static InputStream getStream(URL url) throws IOException {
		if (url != null) {

			return url.openStream();

		} else {
			return null;
		}
	}

	/**
	 * 
	 * @param relativePath必须传递资源的相对路径
	 *            。是相对于classpath的路径。如果需要查找classpath外部的资源，需要使用../来查找
	 * @return
	 * @throws MalformedURLException
	 * @throws IOException
	 */
	public static InputStream getStreamByExtendResource(String relativePath) throws MalformedURLException, IOException {
		return getStream(getExtendResource(relativePath));

	}

	/**
	 * 提供相对于classpath的资源路径，返回文件的输入流
	 * 
	 * @param relativePath必须传递资源的相对路径
	 *            。是相对于classpath的路径。如果需要查找classpath外部的资源，需要使用../来查找
	 * @return 文件输入流
	 * @throwsIOException
	 * @throwsMalformedURLException
	 */
	public static InputStream getStream(String relativePath) throws MalformedURLException, IOException {
		if (!relativePath.contains("../")) {
			return getClassLoader().getResourceAsStream(relativePath);

		} else {
			return getStreamByExtendResource(relativePath);
		}

	}

	/**
	 * 提供相对于classpath的资源路径，返回属性对象，它是一个散列表
	 * 
	 * @paramresource
	 * @return
	 */
	public static Properties getProperties(String resource) {
		Properties properties = new Properties();
		try {
			properties.load(getStream(resource));
		} catch (IOException e) {
			throw new RuntimeException("couldn't load properties file '" + resource + "'", e);
		}
		return properties;
	}

	/**
	 * 得到本Class所在的ClassLoader的Classpat的绝对路径。 URL形式的
	 * 
	 * @return
	 */
	public static String getAbsolutePathOfClassLoaderClassPath() {
		System.out.println(getClassLoader().getResource("").toString());
		return getClassLoader().getResource("").toString();

	}

	public static URL getAbsoluteURLOfClassLoaderClassPath() {
		return getClassLoader().getResource("");
	}

	/**
	 * 
	 * @paramresource
	 * @return
	 */
	public static URL getResource(String resource) {
		System.out.println("传入的相对于classpath的路径：" + resource);
		return getClassLoader().getResource(resource);
	}

	// 加载一个资源
	public static URL getResource(String resourceName, Class callingClass) {
		URL url = Thread.currentThread().getContextClassLoader().getResource(resourceName);

		if (url == null) {
			url = ClassLoaderUtil.class.getClassLoader().getResource(resourceName);
		}

		if (url == null) {
			ClassLoader cl = callingClass.getClassLoader();

			if (cl != null) {
				url = cl.getResource(resourceName);
			}
		}

		if ((url == null) && (resourceName != null) && (resourceName.charAt(0) != '/')) {
			return getResource('/' + resourceName, callingClass);
		}

		return url;
	}

	/**
	 * 加载一个资源以流的形式返回
	 */
	public static InputStream getResourceAsStream(String resourceName, Class callingClass) {
		URL url = getResource(resourceName, callingClass);

		try {
			return (url != null) ? url.openStream() : null;
		} catch (IOException e) {
			return null;
		}
	}

	// 加载class
	/**
	 * 例如:loadClass(clazz.trim(), getClass()).newInstance();
	 */
	public static Class loadClass(String className, Class callingClass) throws ClassNotFoundException {
		try {
			return Thread.currentThread().getContextClassLoader().loadClass(className);
		} catch (ClassNotFoundException e) {
			try {
				return Class.forName(className);
			} catch (ClassNotFoundException ex) {
				try {
					return ClassLoaderUtil.class.getClassLoader().loadClass(className);
				} catch (ClassNotFoundException exc) {
					return callingClass.getClassLoader().loadClass(className);
				}
			}
		}
	}

	/**
	 * 调用一个对象的方法
	 * 
	 * @param obj
	 * @param methodName
	 * @param pars
	 * @return 2008-7-31
	 */
	public static Object invokeMethod(Object obj, String methodName, Object[] pars) {

		try {
			Class[] c = null;
			if (pars != null) {
				c = new Class[pars.length];
				for (int i = 0; i < pars.length; i++) {
					c[i] = pars[i].getClass();
				}
			}
			Method method = obj.getClass().getMethod(methodName, c);
			return method.invoke(obj, pars);

		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 调用一个对象的方法
	 * 
	 * @param className 类名，完整路径
	 * @param methodName 方法名
	 * @param pars	参数
	 * @return 返回值
	 */
	public static Object invokeMethod(String className, String methodName, Object[] pars) {

		try {
			Class[] c = null;
			if (pars != null) {
				c = new Class[pars.length];
				for (int i = 0; i < pars.length; i++) {
					c[i] = pars[i].getClass();
				}
			}
			Object obj = ClassLoaderUtil.loadClassForObject(className);
			Method method = obj.getClass().getMethod(methodName, c);
			return method.invoke(obj, pars);

		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * @paramargs
	 * @throwsMalformedURLException
	 */
	public static void main(String[] args) throws MalformedURLException {

		// getExtendResource("../spring/dao.xml");
		// getExtendResource("../../../src/log4j.properties");
		URL u = getExtendResource("log4j.properties");
		System.out.println(u.toString());
		System.out.println(getClassLoader().getResource("log4j.properties").toString());
		System.out.println(getAbsolutePathOfClassLoaderClassPath());

	}

	
	/**
	 * 从后剪切字符串
	 * @paramsource
	 * @paramdest
	 * @paramnum
	 * @return
	 */
	public static String cutLastString(String source, String dest, int num) {
		// String cutSource=null;
		for (int i = 0; i < num; i++) {
			source = source.substring(0, source.lastIndexOf(dest, source
					.length() - 2) + 1);

		}

		return source;
	}

	/**
	 * 得到资源含有目标的数量
	 * @param source
	 * @param dest
	 * @return
	 * 2008-7-31
	 */
	public static int containSum(String source, String dest) {
		int containSum = 0;
		int destLength = dest.length();
		while (source.contains(dest)) {
			containSum = containSum + 1;
			source = source.substring(destLength);
		}
		return containSum;
	}
}
